Cross-Site Request Forgery (CSRF) is a type of attack used to trick the victim into sending a malicious request. It utilises the identity and privileges of the target in order to perform an undesired action on the victim's behalf. It is similar to indirect impersonation - you can make the victim's browser submit requests as the victim. It is called "cross-site" because a malicious website can make the victim's browser send a request to another website.
This attack typically relies on the victim being authenticated - either through cookies or basic header authorization.
There are two primary types of CSRF - through GET
requests and through POST
requests (although methods like PUT
and DELETE
may also be exploitable).
When your browser submits a request to a web server, it also sends along all stored cookies. If CSRF occurs, any authentication cookies will be sent with the request and as such, any actions on the server would be performed on the victim's behalf. Note that in order for CSRF to work, the victim needs to be logged in because when you make a log out request, the web server usually returns an HTTP response which auto-expires your authentication cookies and they are no longer valid.
In order for it to work, the victim would need to visit your malicious website.
This typically relies on hidden images through the HTML <img>
tag. This tag takes an src
attribute which will tell the victim's browser to perform a GET
request to the specified URL in order to retrieve an image. However, an attacker can change this URL and even add parameters to it, so that the browser performs a GET
request to any arbitrary site.
An example of such a malicious hidden image could be this:
<img src="http://bank.com/transfer?recipient=John&amount=1000" width="0" height="0" border="0">
When visiting your malicious site, this will make the victim's browser submit a GET
request. Any cookies stored for bank.com
would be sent along, including any authentication ones. As such, the bank would complete the transfer from the victim's account.
If the bank uses POST
requests for transfers, the <img>
method won't work because image tags can't initiate POST
requests. This can however be achieved through hidden forms.
<iframe style="display:none" name="csrf-frame"></iframe>
<form method='POST' action='http://bank.com/transfer' target="csrf-frame"
id="csrf-form">
<input type='hidden' name='recipient' value='John'>
<input type='hidden' name='amount' value='1000'>
<input type='submit' value='submit'>
</form>
<script>document.getElementById("csrf-form").submit()</script>
Normally, the submition of the form will require that a user clicks the submit button, but this can be automated through Javascript. The response from the submission of the POST
request would be redirect to the non-displayed iframe and so the victim would never see what has happened.
Sometimes, websites will make use of two-part tokens called CSRF tokens in order to prevent cross-site request forgery. These tokens are generated on the server - one part is sent to the user and the other is kept private. This value is submitted with the request and validated on the server. If the CSRF token isn't correct, the server shouldn't fulfill the submission.
These tokens may be part of the POST
request's body or as custom HTTP headers. They may take on any name, but some common ones include CSRF
, CSRFToken
, X-CSRF-TOKEN
, form-id
, lt
, lia-token
, etc.
You should always try removing or altering the CSRF token in order to check if it's properly implemented.
When a browser sends an
application/json
POST
request to a site, it will send an OPTIONS
request beforehand. The site then returns a
response indicating which types of HTTP
requests the server accepts and from what trusted origins. Such OPTIONS
requests are called preflight OPTIONS
requests.
CORS, or Cross-Origin Resource Sharing, restricts resource access, including JSON response access, from domains outside the one which served a file is allowed by the site being tested. When CORS is used, submitting application/json
requests are not possible, unless the website explicitly allows them.
These protections can sometimes be bypassed by changing the content-type
header to application/x- www-form-urlencoded
, multipart/form-data
, or text/plain
. Browsers don't send preflight OPTIONS
requests for any of these content types and CSRF requests might succeed.
Checking the Origin
and Referer
headers (if the origin header isn't present) prevents CSRF because these headers are controlled by the browsers and cannot be altered by the attacker
This attribute can take on the values strict
or lax
. When set to strict
, the browser won't send that specific cookie with any request that doesn't originate from the correct website - including GET
requests.
Setting the attribute to lax
will prevent the cookie from being sent on normal subrequests (such as loading images or frames), however, the cookie will still be sent with direct requests to the origin site (such as those initiated by clicking on a link).